from pyim import logger
from pyim import config, errcode
from pyim.handler import BaseHandler
from pyim.packet import Packet
from pyim.connection import Connection
from pyim.errcode import ImError
from pyim.user import User
from pyim import auth


class Handler(BaseHandler):
    def on_disconnect(self, connection):
        if not auth.is_logged_in(connection):
            return

        user = connection.user
        user["is_online"] = 0
        presence = Packet(command="presence",
                          username=user.username,
                          status=0)
        for u in User.manager.users():
            if user != u:
                presence["receiver"] = u.username
                u.connection.route(presence)
        auth.logout(connection)

    def handle(self, connection, packet):
        assert isinstance(connection, Connection)
        # test the max number of the clients.
        if len(User.manager) >= config.max_clients:
            raise ImError(errcode.TOO_MANY_CLIENTS)

        sender = auth.authenticate(packet["sender"], password=packet["password"])
        if not sender:
            raise ImError(errcode.INVALID_USER)

        if User.manager[sender.get_auth_id()]:
            raise ImError(errcode.USER_ONLINE_ALREADY)

        logger.debug("Authenticated user successfully.")
        sender['is_online'] = 1
        if self.on_disconnect not in connection.disconnect_callbacks:
            connection.disconnect_callbacks.append(self.on_disconnect)

        # 如果用户上线，将会通过广播的方式通知在线用户
        for user in User.manager.users():
            user.connection.route(Packet(id=packet["id"],
                                         command="presence",
                                         receiver=user.username,
                                         username=packet["sender"],
                                         status=1))

        reply = Packet(id=packet.id,
                       command=packet["command"],
                       receiver=packet["sender"],
                       properties=User.manager.get_properties(packet["sender"]))
        auth.login(connection, sender)
        connection.route(reply)
